package com.xyh.builder;

import com.xyh.bean.Constants;
import com.xyh.bean.FieldInfo;
import com.xyh.bean.TableInfo;
import com.xyh.utils.DateUtils;
import com.xyh.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class BuildMapper {
    private static final Logger logger = LoggerFactory.getLogger(BuildMapper.class);

    public static void execute(TableInfo tableInfo) {
        // 初始化目录和文件
        File poDir = new File(Constants.PATH_MAPPER);
        if (!poDir.exists() && !poDir.mkdirs()) {
            logger.error("创建PO目录失败: {}", Constants.PATH_MAPPER);
            return;
        }

        File poFile = new File(poDir, tableInfo.getBeanName()+Constants.SUFFIX_MAPPER + ".java");

        // 生成PO类
        try (BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(poFile), StandardCharsets.UTF_8))) {
            writePackage(bw); // 包声明
            writeImports(bw, tableInfo); // 导包区域
            writeClassComment(bw, tableInfo); // 类注释
            writeClassDefinition(bw, tableInfo); // 类定义
            writeFields(bw, tableInfo.getFieldList(), tableInfo.getKeyIndexMap()); // 字段生成
            bw.newLine();
            bw.write("}");
            bw.flush();
            logger.info("生成Mapper成功: {}", poFile.getAbsolutePath());
        } catch (Exception e) {
            logger.error("生成Mapper失败: 表名={}", tableInfo.getTableName(), e);
        }

    }

    private static void writeFields(BufferedWriter bw, List<FieldInfo> fieldList, Map<String, List<FieldInfo>> keyIndexMap) throws IOException {
        //用来记录主键的名字
        Set<String> keyFieldNameSet = new HashSet<>();
        for (Map.Entry<String, List<FieldInfo>> entry : keyIndexMap.entrySet()) {
            List<FieldInfo> keyFieldList = entry.getValue();
            Integer index = 0;
            StringBuffer methodName = new StringBuffer();
            StringBuffer methodParams = new StringBuffer();
            for (FieldInfo fieldInfo : keyFieldList) {
               index++;
               methodName.append(StringUtils.upperCaseFirstLetter(fieldInfo.getPropertyName()));
               if(index<keyFieldList.size()){
                   methodName.append("And");
               }
               methodParams.append("@Param("+"\""+fieldInfo.getPropertyName()+"\""+ ") " +fieldInfo.getJavaType() + " " + fieldInfo.getPropertyName()  );
               if(index<keyFieldList.size()){
                   methodParams.append(",");
               }
               keyFieldNameSet.add(fieldInfo.getPropertyName());
            }

            writeFieldComment(bw, "根据"+methodName + "查询");
            bw.write("\tT selectBy"+methodName+"("+ methodParams+");");
            bw.newLine();
            bw.newLine();

            writeFieldComment(bw, "根据"+methodName + "更新");
            bw.write("\tLong updateBy"+methodName+"( @Param(\"bean\") T entity, "+ methodParams+ ");");
            bw.newLine();
            bw.newLine();

            writeFieldComment(bw, "根据"+methodName + "删除");
            bw.write("\tLong deleteBy"+methodName+"("+methodParams +");");
            bw.newLine();
            bw.newLine();
        }

        //根据id删除
        for (FieldInfo fieldInfo : fieldList) {
            if(!keyFieldNameSet.contains(fieldInfo.getPropertyName()) && fieldInfo.getPropertyName().toLowerCase().endsWith("id")){
                writeFieldComment(bw, "根据"+fieldInfo.getPropertyName() + "删除");
                bw.write("\tLong deleteBy"+StringUtils.upperCaseFirstLetter(fieldInfo.getPropertyName())+"("+fieldInfo.getJavaType() + " " + fieldInfo.getPropertyName()+");");
                bw.newLine();
            }
        }

    }

    private static void writeFieldComment(BufferedWriter bw, String comment) throws IOException {
        bw.write("\t/** ");
        bw.newLine();
        if (comment != null && !comment.isEmpty()) {
            bw.write("\t * " + comment);
            bw.newLine();
        } else {
            bw.write("\t * ");
            bw.newLine();
        }
        bw.write("\t */");
        bw.newLine();
    }

    private static void writeClassDefinition(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("@Mapper");
        bw.newLine();
        bw.write("public interface " + tableInfo.getBeanName()+ Constants.SUFFIX_MAPPER +"<T, P>"+ " extends BaseMapperEx<T, P> {");
        bw.newLine();
        bw.newLine();
    }

    private static void writeClassComment(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("/**");
        bw.newLine();
        bw.write(" * " + (null != tableInfo.getComment() ? tableInfo.getComment() : tableInfo.getBeanName()) + " Mapper接口");
        bw.newLine();
        bw.write(" * ");
        bw.newLine();
        bw.write(" * 对应数据库表: " + tableInfo.getTableName());
        bw.newLine();
        bw.write(" * @author " + Constants.AUTHOR);
        bw.newLine();
        bw.write(" * @date " + DateUtils.format(new Date(), DateUtils.YYYY_MM_DD_HH_MM_SS));
        bw.newLine();
        bw.write(" */");
        bw.newLine();
    }

    private static void writeImports(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("import org.apache.ibatis.annotations.Mapper;");
        bw.newLine();
        bw.write("import org.apache.ibatis.annotations.Param;");
        bw.newLine();
        bw.write("import java.util.Map;");
        bw.newLine();
    }

    private static void writePackage(BufferedWriter bw) throws IOException {
        bw.write("package " + Constants.PACKAGE_MAPPER + ";");
        bw.newLine();
        bw.newLine();
    }
}
